package com.lock.controller;

import com.lock.content.Result;
import com.lock.request.StockRequest;
import com.lock.service.PessimisticLockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/pessimistic")
public class PessimisticLockController {
    @Autowired
    private PessimisticLockService pessimisticLockService;

    /**
     * 基于数据库悲观锁的库存扣减接口
     * 通过 SELECT ... FOR UPDATE 实现行级锁，确保同一时间只有一个事务可以修改库存
     * 适用于高并发、写冲突频繁的库存管理场景，防止超卖和库存不一致问题
     *
     * 当执行 SELECT ... FOR UPDATE 时，数据库会对查询结果中的记录加 排他锁（X 锁），具体表现为：
     * 阻止其他事务修改
     * 其他事务无法对锁定的记录执行 UPDATE、DELETE 或 SELECT ... FOR UPDATE，需等待锁释放。
     * 不阻止普通查询
     * 其他事务仍可使用 SELECT 正常读取记录（但可能读到未提交的数据，取决于隔离级别）。
     * 事务提交或回滚后释放锁
     * 锁的持有时间从 SELECT ... FOR UPDATE 执行开始，到当前事务结束（COMMIT 或 ROLLBACK）。
     */
    @PostMapping("/db/decreaseStock")
    public Result<?> decreaseStockByDbLock(@RequestBody StockRequest request) {
        boolean success = pessimisticLockService.decreaseStockByDbLock(
                request.getProductId(), request.getQuantity());
        return success ? Result.success() : Result.fail("库存不足");
    }

    /**
     * 基于 Redis 分布式锁的库存扣减接口
     * 通过 SETNX 原语实现分布式锁，确保跨节点的并发操作互斥
     * 适用于微服务架构下的库存共享场景，支持水平扩展和高可用
     */
    @PostMapping("/redis/decreaseStock")
    public Result<?> decreaseStockByRedisLock(@RequestBody StockRequest request) {
        boolean success = pessimisticLockService.decreaseStockByRedisLock(
                request.getProductId(), request.getQuantity());
        return success ? Result.success() : Result.fail("库存不足或获取锁失败");
    }

    /**
     * 基于 synchronized 分布式锁的库存扣减接口
     */
    @PostMapping("/synchronized/decreaseStock")
    public Result<?> decreaseStockBySynchronized(@RequestBody StockRequest request) {
        boolean success = pessimisticLockService.decreaseStockBySynchronized(
                request.getProductId(), request.getQuantity());
        return success ? Result.success() : Result.fail("库存不足或获取锁失败");
    }
}